package com.mvw.tetrominoes.data {
	
	import mx.containers.Canvas;	
	
	/**
	 * A series of 4 adjacent cells.
	 */
	public class Cluster {
		
		private var _type:ClusterType;
		private var _orientation:ClusterOrientation;
		private var _direction:ClusterDirection;
		
		public var cellOne:Cell;
		public var cellTwo:Cell;
		public var cellThree:Cell;
		public var cellFour:Cell;
		
		/**
		 * The constructor picks a random ClusterType and initializes the Cluster to a
		 * HORIZONTAL orientation with LEFT direction.
		 */
		public function Cluster():void {
			
			_type = ClusterType.random;
			_orientation = ClusterOrientation.HORIZONTAL;
			_direction = ClusterDirection.LEFT;
			
			if (this.type.toString() == ClusterType.I.toString()) {
				//I
				cellOne = new Cell(3,0);
				cellTwo = new Cell(4,0);
				cellThree = new Cell(5,0);
				cellFour = new Cell(6,0);
			}
			else if (this.type.toString() == ClusterType.J.toString()) {
				//J
				cellOne = new Cell(4,0);
				cellTwo = new Cell(5,0);
				cellThree = new Cell(6,0);
				cellFour = new Cell(6,1);
			}
			else if (this.type.toString() == ClusterType.L.toString()) {
				//L
				cellOne = new Cell(4,0);
				cellTwo = new Cell(4,1);
				cellThree = new Cell(5,0);
				cellFour = new Cell(6,0);
			}
			else if (this.type.toString() == ClusterType.O.toString()) {
				//O
				cellOne = new Cell(4,0);
				cellTwo = new Cell(4,1);
				cellThree = new Cell(5,0);
				cellFour = new Cell(5,1);
			}
			else if (this.type.toString() == ClusterType.S.toString()) {
				//S
				cellOne = new Cell(4,1);
				cellTwo = new Cell(5,1);
				cellThree = new Cell(5,0);
				cellFour = new Cell(6,0);
			}
			else if (this.type.toString() == ClusterType.T.toString()) {
				//T
				cellOne = new Cell(4,0);
				cellTwo = new Cell(5,0);
				cellThree = new Cell(5,1);
				cellFour = new Cell(6,0);
			}
			else if (this.type.toString() == ClusterType.Z.toString()) {
				//Z
				cellOne = new Cell(4,0);
				cellTwo = new Cell(5,0);
				cellThree = new Cell(5,1);
				cellFour = new Cell(6,1);
			}
			else {
				throw new Error("Unknown Type (" + this.type + ")");
			}
		}
		
		/**
		 * The type of Cluster.
		 * 
		 * @return An instance of ClusterType.
		 */
		public function get type():ClusterType {
			return _type;
		}
		
		/**
		 * The orientation of Cluster.
		 * Not applicable to ClusterType.O.
		 * 
		 * @return An instance of ClusterOrientation.
		 */
		public function get orientation():ClusterOrientation {
			return _orientation;
		}
		
		/**
		 * The direction of Cluster.
		 * Only application to ClusterType.L and ClusterType.J.
		 * 
		 * @return An instance of ClusterType.
		 */
		public function get direction():ClusterDirection {
			return _direction;
		}	
		
		/**
		 * Simulates leftward movement.
		 * 
		 * @param plane An instance of Plane.
		 */
		public function moveLeftRelativeToPlane(plane:Plane):void {
			if (cellOne.x && cellTwo.x && cellThree.x && cellFour.x) {
				
				if (!(plane.isCellAt(cellOne.y, cellOne.x-1) || plane.isCellAt(cellTwo.y, cellTwo.x-1) ||
					plane.isCellAt(cellThree.y, cellThree.x-1) || plane.isCellAt(cellFour.y, cellFour.x-1))) {
							
					cellOne.x = cellOne.x - 1;
					cellTwo.x = cellTwo.x - 1;
					cellThree.x = cellThree.x - 1;
					cellFour.x = cellFour.x - 1;
				}
			}
		}
		
		/**
		 * Simulates rightward movement.
		 * 
		 * @param plane An instance of Plane.
		 */
		public function moveRightRelativeToPlane(plane:Plane):void {
			if (cellOne.x < plane.width-1 && cellTwo.x < plane.width-1 && 
				cellThree.x < plane.width-1 && cellFour.x < plane.width-1) {
					
				if (!(plane.isCellAt(cellOne.y, cellOne.x+1) || plane.isCellAt(cellTwo.y, cellTwo.x+1) ||
					plane.isCellAt(cellThree.y, cellThree.x+1) || plane.isCellAt(cellFour.y, cellFour.x+1))) {
					
					cellOne.x = cellOne.x + 1;
					cellTwo.x = cellTwo.x + 1;
					cellThree.x = cellThree.x + 1;
					cellFour.x = cellFour.x + 1;
				}
			}
		}
		
		/**
		 * Simulates downward movement.
		 * 
		 * @param plane An instance of Plane.
		 * 
		 * @return Indicates whether or not the cluster has landed.
		 */
		public function moveDownRelativeToPlane(plane:Plane):Boolean {
			if (cellOne.y < plane.height-1 && cellTwo.y < plane.height-1 && 
				cellThree.y < plane.height-1 && cellFour.y < plane.height-1) {
					
				if (plane.isCellAt(cellOne.y+1, cellOne.x) || plane.isCellAt(cellTwo.y+1, cellTwo.x) ||
					plane.isCellAt(cellThree.y+1, cellThree.x) || plane.isCellAt(cellFour.y+1, cellFour.x)) {
					
					return false;	
				}
				else {
					cellOne.y = cellOne.y + 1;
					cellTwo.y = cellTwo.y + 1;
					cellThree.y = cellThree.y + 1;
					cellFour.y = cellFour.y + 1;
					return true;
				}
			}
			else {
				return false;
			}
		}
		
		/**
		 * Rotates the cluster relative to a Plane of existing Cell objects.
		 * 
		 * @param plan An instance of Plane.
		 */
		public function rotateRelativeToPlane(plane:Plane):void {
			if (this.type.toString() == ClusterType.I.toString()) {
				//I
				if (this.orientation == ClusterOrientation.HORIZONTAL) {
					
					if (!(plane.isCellAt(cellThree.y-1, cellThree.x) || plane.isCellAt(cellThree.y+1, cellThree.x) ||
						plane.isCellAt(cellThree.y-2, cellThree.x))) {
							
						cellTwo.x = cellThree.x;
						cellTwo.y = cellThree.y - 1;
						cellFour.x = cellThree.x;
						cellFour.y = cellThree.y + 1;
						cellOne.x = cellThree.x;
						cellOne.y = cellThree.y - 2;
						
						_orientation = ClusterOrientation.VERTICAL;
					}
				}
				else if (this.orientation == ClusterOrientation.VERTICAL) {
					
					if (!(plane.isCellAt(cellThree.y, cellThree.x-2) || plane.isCellAt(cellThree.y, cellThree.x-1) ||
						plane.isCellAt(cellThree.y, cellThree.x+1))) {
					
						cellOne.x = cellThree.x - 2;
						cellOne.y = cellThree.y;
						cellTwo.x = cellThree.x - 1;
						cellTwo.y = cellThree.y;
						cellFour.x = cellThree.x + 1;
						cellFour.y = cellThree.y;
					
						_orientation = ClusterOrientation.HORIZONTAL;	
					}
				}
				else {
					throw new Error("Unknown ClusterOrientation (" + this.orientation + ")");
				}
			}
			else if (this.type.toString() == ClusterType.J.toString()) {
				//J
				if (this.orientation == ClusterOrientation.HORIZONTAL && 
					this.direction == ClusterDirection.LEFT) {
					
					if (!(plane.isCellAt(cellOne.y+1, cellOne.x) || plane.isCellAt(cellTwo.y-1, cellTwo.x) ||
						plane.isCellAt(cellThree.y, cellThree.x-1) || plane.isCellAt(cellFour.y, cellFour.x-1))) {
					
						cellOne.y += 1;
						cellTwo.y += -1;
						cellThree.x += -1;
						cellFour.x += -1;
					
						_orientation = ClusterOrientation.VERTICAL;		
					}
				}
				else if (this.orientation == ClusterOrientation.VERTICAL &&
					this.direction == ClusterDirection.LEFT) {
					
					if (!(plane.isCellAt(cellOne.y-2, cellOne.x) || plane.isCellAt(cellFour.y+1, cellFour.x+1) ||
						plane.isCellAt(cellTwo.y-1, cellTwo.x-1))) {
					
						cellOne.y += -2;
						cellTwo.x += -1;
						cellTwo.y += 1;
						cellFour.x += 1;
						cellFour.y += -1;
						
						_orientation = ClusterOrientation.HORIZONTAL;
						_direction = ClusterDirection.RIGHT;	
					}
				}
				else if (this.orientation == ClusterOrientation.HORIZONTAL &&
					this.direction == ClusterDirection.RIGHT) {
					
					if (!(plane.isCellAt(cellOne.y, cellOne.x+1) || plane.isCellAt(cellThree.y+1, cellThree.x) ||
						plane.isCellAt(cellTwo.y, cellTwo.x+1) || plane.isCellAt(cellFour.y-1, cellFour.x))) {
							
						cellOne.x += 1
						cellTwo.x += 1;
						cellThree.y += 1;
						cellFour.y += -1;
						
						_orientation = ClusterOrientation.VERTICAL;	
					}
				}
				else if (this.orientation == ClusterOrientation.VERTICAL &&
					this.direction == ClusterDirection.RIGHT) {
					
					if (!(plane.isCellAt(cellOne.y+1, cellOne.x-1) || plane.isCellAt(cellFour.y+2, cellFour.x) ||
						plane.isCellAt(cellThree.y-1, cellThree.x+1))) {
							
						cellOne.x += -1;
						cellOne.y += 1;
						cellThree.x += 1;
						cellThree.y += -1;
						cellFour.y += 2;
						
						_orientation = ClusterOrientation.HORIZONTAL;
						_direction = ClusterDirection.LEFT;
					}
				}
				else {
					throw new Error("Unknown ClusterOrientation or ClusterDirection (" + 
						this.orientation + ", " + this.direction + ")");
				}
			}
			else if (this.type.toString() == ClusterType.L.toString()) {
				//L
				if (this.orientation == ClusterOrientation.HORIZONTAL && 
					this.direction == ClusterDirection.LEFT) {
					
					if (!(plane.isCellAt(cellOne.y-1, cellOne.x) || plane.isCellAt(cellTwo.y-2, cellTwo.x+1) ||
						plane.isCellAt(cellFour.y+1, cellFour.x-1))) {
					
						cellOne.y += -1;
						cellTwo.x += 1;
						cellTwo.y += -2;
						cellFour.x += -1;
						cellFour.y += 1;
						
						_orientation = ClusterOrientation.VERTICAL;	
					}
				}
				else if (this.orientation == ClusterOrientation.VERTICAL &&
					this.direction == ClusterDirection.LEFT) {
					
					if (!(plane.isCellAt(cellOne.y+1, cellOne.x) || plane.isCellAt(cellTwo.y+1, cellTwo.x) ||
						plane.isCellAt(cellThree.y, cellThree.x+1) || plane.isCellAt(cellFour.y-2, cellFour.x+1))) {
					
						cellOne.y += 1;
						cellTwo.y += 1;
						cellThree.x += 1;
						cellFour.x += 1;
						cellFour.y += -2;
						
						_orientation = ClusterOrientation.HORIZONTAL;
						_direction = ClusterDirection.RIGHT;	
					}
				}
				else if (this.orientation == ClusterOrientation.HORIZONTAL &&
					this.direction == ClusterDirection.RIGHT) {
					
					if (!(plane.isCellAt(cellOne.y-1, cellOne.x+1) ||
						plane.isCellAt(cellThree.y+1, cellThree.x-1) || plane.isCellAt(cellFour.y+2, cellFour.x))) {
							
						cellOne.x += 1;
						cellOne.y += -1;
						cellThree.x += -1;
						cellThree.y += 1;
						cellFour.y += 2;
						
						_orientation = ClusterOrientation.VERTICAL;
					}
				}
				else if (this.orientation == ClusterOrientation.VERTICAL &&
					this.direction == ClusterDirection.RIGHT) {
					
					if (!(plane.isCellAt(cellOne.y+1, cellOne.x-1) || plane.isCellAt(cellTwo.y+1, cellTwo.x-1) ||
						plane.isCellAt(cellThree.y-1, cellThree.x) || plane.isCellAt(cellFour.y-1, cellFour.x))) {
							
						cellOne.x += -1;
						cellOne.y += 1;
						cellTwo.x += -1;
						cellTwo.y += 1;
						cellThree.y += -1;
						cellFour.y += -1;
						
						_orientation = ClusterOrientation.HORIZONTAL;
						_direction = ClusterDirection.LEFT;
					}
				}
				else {
					throw new Error("Unknown ClusterOrientation or ClusterDirection (" + 
						this.orientation + ", " + this.direction + ")");
				}
			}
			else if (this.type.toString() == ClusterType.O.toString()) {
				//O: No rotation
			}
			else if (this.type.toString() == ClusterType.S.toString()) {
				//S
				if (this.orientation == ClusterOrientation.HORIZONTAL) {
					
					if (!(plane.isCellAt(cellOne.y-2, cellOne.x) || plane.isCellAt(cellTwo.y-1, cellTwo.x-1) ||
						plane.isCellAt(cellFour.y+1, cellFour.x-1))) {
							
						cellOne.y += -2;
						cellTwo.x += -1;
						cellTwo.y += -1
						cellFour.x += -1;
						cellFour.y += 1;
						
						_orientation = ClusterOrientation.VERTICAL;
					}
				}
				else if (this.orientation == ClusterOrientation.VERTICAL) {
					
					if (!(plane.isCellAt(cellOne.y+2, cellOne.x) || plane.isCellAt(cellTwo.y+1, cellTwo.x+1) ||
						plane.isCellAt(cellFour.y-1, cellFour.x+1))) {
					
						cellOne.y += 2;
						cellTwo.x += 1;
						cellTwo.y += 1;
						cellFour.x += 1;
						cellFour.y += -1;
						
						_orientation = ClusterOrientation.HORIZONTAL;
					}
				}
				else {
					throw new Error("Unknown ClusterOrientation (" + this.orientation + ")");
				}
			}
			else if (this.type.toString() == ClusterType.T.toString()) {
				//T
				if (this.orientation == ClusterOrientation.HORIZONTAL && 
					this.direction == ClusterDirection.LEFT) {
					
					if (!(plane.isCellAt(cellTwo.y-1, cellTwo.x) || plane.isCellAt(cellThree.y-1, cellThree.x) ||
						plane.isCellAt(cellFour.y+1, cellFour.x-1))) {
					
						cellTwo.y += -1;
						cellThree.y += -1;
						cellFour.x += -1;
						cellFour.y += 1;
						
						_orientation = ClusterOrientation.VERTICAL;	
					}
				}
				else if (this.orientation == ClusterOrientation.VERTICAL &&
					this.direction == ClusterDirection.LEFT) {
					
					if (!(plane.isCellAt(cellFour.y-1, cellFour.x+1))) {
					
						cellFour.x += 1;
						cellFour.y += -1;
						
						_orientation = ClusterOrientation.HORIZONTAL;
						_direction = ClusterDirection.RIGHT;	
					}
				}
				else if (this.orientation == ClusterOrientation.HORIZONTAL &&
					this.direction == ClusterDirection.RIGHT) {
					
					if (!(plane.isCellAt(cellOne.y-1, cellOne.x+1) || plane.isCellAt(cellThree.y+1, cellThree.x) ||
						plane.isCellAt(cellTwo.y+1, cellTwo.x))) {
							
						cellOne.x += 1
						cellOne.y += -1;
						cellTwo.y += 1;
						cellThree.y += 1;
						
						_orientation = ClusterOrientation.VERTICAL;	
					}
				}
				else if (this.orientation == ClusterOrientation.VERTICAL &&
					this.direction == ClusterDirection.RIGHT) {
					
					if (!(plane.isCellAt(cellOne.y+1, cellOne.x-1))) {
							
						cellOne.x += -1;
						cellOne.y += 1;
						
						_orientation = ClusterOrientation.HORIZONTAL;
						_direction = ClusterDirection.LEFT;
					}
				}
				else {
					throw new Error("Unknown ClusterOrientation or ClusterDirection (" + 
						this.orientation + ", " + this.direction + ")");
				}
			}
			else if (this.type.toString() == ClusterType.Z.toString()) {
				//Z
				if (this.orientation == ClusterOrientation.HORIZONTAL) {
					
					if (!(plane.isCellAt(cellOne.y+1, cellOne.x) || plane.isCellAt(cellTwo.y, cellTwo.x-1) ||
						plane.isCellAt(cellThree.y-1, cellThree.x) || plane.isCellAt(cellFour.y-2, cellFour.x-1))) {
							
						cellOne.y += 1;
						cellTwo.x += -1;
						cellThree.y += -1;
						cellFour.x += -1;
						cellFour.y += -2;
						
						_orientation = ClusterOrientation.VERTICAL;
					}
				}
				else if (this.orientation == ClusterOrientation.VERTICAL) {
					
					if (!(plane.isCellAt(cellOne.y-1, cellOne.x) || plane.isCellAt(cellTwo.y, cellTwo.x+1) ||
						plane.isCellAt(cellThree.y-1, cellFour.x) || plane.isCellAt(cellFour.y+2, cellFour.x+1))) {
					
						cellOne.y += -1;
						cellTwo.x += 1;
						cellThree.y += 1;
						cellFour.x += 1;
						cellFour.y += 2;
						
						_orientation = ClusterOrientation.HORIZONTAL;
					}
				}
				else {
					throw new Error("Unknown ClusterOrientation (" + this.orientation + ")");
				}
			}
			else {
				throw new Error("Unknown Type (" + this.type + ")");
			}
		}

	}
}